' debugtree.bmx

Strict

Import brl.retro

Import "nodeview.bmx"
Import "host.bmx"
Import "outputpanel.bmx"

Type TObj
	Field	addr$,sync,refs
End Type

Type TVar Extends TDataNode

	Field	owner:TDebugTree
	Field	obj:Object

	Method Free()
		If obj owner.RemoveObj obj
		obj=Null
		Super.Free()
	End Method

	Method SetVarName(n$)
		Local	p
		name=n
' if object ref set addr$ field	
		If name.find("$=")=-1 And name.find(")=$")=-1
			p=name.find("=$")
			If p<>-1
				TDebugTree.RemoveObj obj
				obj=TDebugTree.AddObj(name[p+2..])
			EndIf
			p=name.find("=Null")
			If p<>-1
				FreeKids
				TDebugTree.RemoveObj obj
				obj=Null
			EndIf
		EndIf
	End Method
	
	Method AddVar(name$)
		Local	v:TVar
		v=New TVar
		v.setvarname name
		v.owner=owner
		Append v
	End Method
	
	Method SetValue(val:TVar)
		Local	v:TVar,w:TVar,i
' if this is a reference to same object refresh values	
		If obj And obj=val.obj
'			sync=val.sync
			If kids.IsEmpty()
				For v=EachIn val.kids
					AddVar v.name
				Next
			Else
				For v=EachIn val.kids
					If i<kids.count()
						w=TVar(kids.ValueAtIndex(i))
						If w w.SetVarName v.name
					Else
						AddVar v.name
					EndIf
					i:+1
				Next			
			EndIf
			Refresh
		EndIf	
' recurse so all references are updated
		If IsHidden() Return				'parent And parent.state=CLOSEDSTATE Return
		For v=EachIn kids
			v.SetValue val
		Next
	End Method
	
	Method Open(view=0)
		owner.sync:+1
		Super.Open view
		owner.SyncVars
	End Method
	
End Type

Type TScope Extends TVar
	Field	tree:TDebugTree
	Field	file$,line,column

	Method Invoke(command$,argument:Object=Null)
		Select command
			Case "ACTIVATE"
				tree.SelectScope Self,True
		End Select
	End Method
	
	Method SetScope(s:TScope)
		Local	v:TVar
		file=s.file
		line=s.line
		column=s.column
		s.obj=Self
		SetValue s
	End Method
	
	Method SetFile(debugtree:TDebugTree,f$)
		Local	p,q,r
		tree=debugtree
		p=Instr(f,"<")
		q=Instr(f,">")
		r=Instr(f,",")
		If p And q And r
			file=f[..p-1]
			line=Int(f[p..r-1])
			column=Int(f[r..q-1])
		EndIf
		obj=Self
	End Method
End Type

Type TDebugTree Extends TVar
	Global	sync
	Global	objlist:TList
	Field	host:THost
	Field	instack:TList
	Field	inscope:TScope
	Field	invar:TVar
	Field	infile$
	Field	inexception$
	Field	firststop
	Field	cancontinue
	Field	canopen:TButton
		
	Function CreateDebugTree:TDebugTree(host:THost,canopenbutton:TButton)
		Local	d:TDebugTree
		objlist=New TList
		d=New TDebugTree
		d.owner=d
		d.canopen=canopenbutton
		d.SetName "Debug"
		d.host=host
		d.Open
		Return d		
	End Function

	Method Invoke(command$,argument:Object=Null)
		If command="RESET" Reset'(TOutputPanel(argument))
	End Method

	Method Reset()
		host.SetMode host.DEBUGMODE
		SetStack New TList
		objlist=New TList	
		instack=Null
		inscope=Null
		invar=Null
		infile=""
		inexception=""
		sync=0
		firststop=True
		cancontinue=False
	End Method

	Function AddObj:TObj(addr$)
		Local	o:TObj
		For o=EachIn objlist
			If o.addr=addr 
				o.refs:+1
				Return o
			EndIf
		Next
		o=New TObj
		o.addr=addr
		o.refs=1
		objlist.addlast o
		Return o
	End Function

	Function FindObj:TObj(addr$)
		Local	o:TObj
		For o=EachIn objlist
			If o.addr=addr Return o
		Next
	End Function
	
	Function RemoveObj(obj:Object)		':TObj
		Local	o:TObj
		o=TObj(obj)
		If Not o Return
		o.refs:-1
		If o.refs=0 
			objlist.Remove o
		EndIf
	End Function

	Method SyncVars()
		Local	o:TObj
		For o=EachIn objlist
			If o.sync<sync 
				o.sync=sync
' simon come here
				host.WriteDebug "d"+o.addr
			EndIf
		Next		
	End Method
			
	Method SetStack(list:TList)
		Local	scope:TScope
		Local	openscope:TScope
		Local	s:TScope
		Local	count,i

		count=kids.count()			'root.varlist.count()
		For scope=EachIn list
			If i>=count
				Append scope		'root.Append scope
				s=scope
			Else
				s=TScope(kids.ValueAtIndex(i))
				If s.name=scope.name
					s.SetScope scope
					scope.Free
				Else
					While kids.count()>i
						s=TScope(kids.ValueAtIndex(i))
						s.free
					Wend
					Append scope
					s=scope
					count=i+1
				EndIf
			EndIf
			If firststop And Not canopen.Selected()
				If host.IsSourceOpen(s.file) openscope=s
			Else
				openscope=s
			EndIf
			i:+1
		Next		
		While kids.count()>i
			scope=TScope(kids.ValueAtIndex(i))
			scope.free
		Wend 
		If list.isempty() Return
		If Not openscope openscope=TScope(list.First())
		If openscope SelectScope openscope,True
		Refresh
		firststop=False
	End Method

	Method SelectScope(scope:TScope,open)
		If Not scope Return		
		If scope.file host.DebugSource scope.file,scope.line,scope.column
		scope.Open
'		If open
'			SelectTreeViewNode scope.node
'			scope.open
'		EndIf
	End Method

	Method Process$(line$)
		Local	p
				
		While line[..1]=">" 
			line=line[1..]
		Wend
		If Not line Return

		If line[..2]<>"~~>" Return line

		line=line[2..]

		If invar
			If line="}"
				SetValue invar		'root
				invar.Free
				invar=Null
			Else
'				If Not invar.name
'					invar.name=line
'				Else
					invar.AddVar line
'				EndIf
			EndIf
			Return
		EndIf
		
		If instack 			
			If line="}" 
				sync:+1
				SetStack instack
				instack=Null
				inscope=Null
				SyncVars
				If inexception
					Notify inexception
					inexception=""
				EndIf
				Return
			EndIf
			
			If infile
				If line="Local <local>"
				Else
					inscope=New TScope
					inscope.name=line
					inscope.owner=Self
					instack.AddLast inscope
				EndIf
				If inscope inscope.setfile Self,infile
				infile=""
				Return
			EndIf

			If Instr(line,"@")=1 And Instr(line,"<")
				infile=line[1..]
			Else
				If inscope inscope.AddVar line
			EndIf

			Return
		EndIf

		If line[..20]="Unhandled Exception:"
			inexception=line
			host.WriteDebug "t"
			cancontinue=False
			Return
		EndIf

		If line="StackTrace{" 
			instack=New TList
			Return
		EndIf

		If line="Debug:" Or line="DebugStop:"
			host.WriteDebug "t"
			cancontinue=True
			Return
		EndIf					
		
		If line[..11]="ObjectDump@"
			p=line.find("{")
			If p=-1 Return line
			line=line[11..p]
			invar=New TVar
'			invar.obj=AddObj(line)
			invar.obj=FindObj(line)	'simon come here
			invar.owner=Self
			Return
		EndIf
		
	End Method

End Type

